/*
  公用工具函数
*/
import storage from 'good-storage'
import { isEmpty } from 'lodash-es';
import { LoginUrl } from 'api/config'
import { userInfoStorageKey, tokenStorageKey } from 'common/js/config'
import XLSXS from 'xlsx-js-style'

// 获取本地存储数据
export const getStorage = (name) => {
  return storage.get(name)
}

// 设置本地存储数据
export const setStorage = (name, val) => {
  return storage.set(name, val)
}

// 删除本地存储数据
export const removeStorage = (name) => {
  return storage.remove(name)
}

// 过滤时间格式
export const timeFilter = (time, format) => {
  var o = {
    'M+': time.getMonth() + 1, // month
    'd+': time.getDate(), // day
    'H+': time.getHours(), // hour
    'm+': time.getMinutes(), // minute
    's+': time.getSeconds(), // second
    'q+': Math.floor((time.getMonth() + 3) / 3), // quarter
    'S': time.getMilliseconds() // millisecond
  }

  if (/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (time.getFullYear() + '').substr(4 - RegExp.$1.length))
  }

  for (var k in o) {
    if (new RegExp('(' + k + ')').test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
    }
  }
  return format
}

// axios post 使用formData格式 的 转换方法
export function changeFormData (json) {
  var a = Object.keys(json).map(
    function (k) {
      return encodeURIComponent(k) + '=' + encodeURIComponent(json[k])
    }
  ).join('&')

  return a
}

// 深拷贝一个Object
export function cloneObj (obj) {
  if (typeof obj !== 'object') {
    return obj
  }
  var s = {}
  if (obj.constructor === Array) {
    s = []
  }
  for (var i in obj) {
    s[i] = cloneObj(obj[i])
  }
  return s
}

let isAlerting = false

// 状态超时或错误时，返回登陆页
export function timeOutAction (str = '登录超时，请重新登录。', isNeedAlert = true) {
  if (isAlerting) {
    return
  }
  isAlerting = true

  if (isNeedAlert) {
    alert(str)
  }

  removeStorage(userInfoStorageKey)
  removeStorage(tokenStorageKey)
  window.location.href = LoginUrl
}

const noDataStr = '--'

// 过滤单层字段
export const fliterData = (data, key) => {
  if (data[key] === 0 || data[key] === '0') {
    return data[key]
  }
  return data[key] || noDataStr
}

// 过滤双层字段
export const fliterDouData = (data, key) => {
  const arr = key.split('.')
  
  if (data[arr[0]] === undefined || data[arr[0]] === null || data[arr[0]] === '') {
    data[arr[0]] = {}
  }

  return data[arr[0]][arr[1]] || noDataStr
}

// 过滤三层字段
export const fliterSanData = (data, key) => {
  const arr = key.split('.')

  if (data[arr[0]] === undefined) {
    data[arr[0]] = {}
  }

  if (data[arr[0]][arr[1]] === undefined) {
    data[arr[0]][arr[1]] = {}
  }

  return data[arr[0]][arr[1]][arr[2]] || noDataStr
}

// 获取模糊查询
export const getLikeSearch = (data, key) => {
  const newData = JSON.parse(JSON.stringify(data))
  const arr = key.split(',')

  arr.map(item => {
    if (newData[item]) {
      newData[item] = `%${newData[item]}%`
    } else {
      delete newData[item]
    }
  })

  return newData
}

// 数组去重
export const removeSame = (arr) => {
  let unique = {}
  arr.forEach(function (item) {
    unique[JSON.stringify(item)] = item
  })
  arr = Object.keys(unique).map(function (u) {
    return JSON.parse(u)
  })
  return arr
}

// 剔除0来判断是否为false
export const isNoEmpty = (val) => {
  if (val === undefined || val === null || val === '') {
    return false
  } else {
    return true
  }
}

export const removeObjUndefined = ({ data = {} }) => {
  const newObj = JSON.parse(JSON.stringify(data))

  for (let key in newObj) {
    if (newObj[key] === undefined || newObj[key] === null) {
      delete newObj[key]
    }
  }

  return newObj
}

export const readExcel = (file) => {
  return new Promise((resolve, reject) => {
    var reader = new FileReader()
    reader.readAsBinaryString(file)
    reader.onload = function (e) {
      var data = e.target.result
      var workbook = XLSX.read(data, { type: 'binary' })

      // 获取工作表名称集合
      var sheetName = workbook.SheetNames[0]
      var worksheet = workbook.Sheets[sheetName]
      var csv = XLSX.utils.sheet_to_json(worksheet)

      resolve(csv)
    }
  })
}

export const filterImgUrl = (str) => {
  if (!str) {
    return '--'
  }

  let newStr = str

  newStr = newStr.replace(/\\|\\\\/g, '/')

  return newStr
}

export const filterEmpty = (str) => {
  if (!str) {
    return ''
  }

  let newStr = String(str)

  newStr = newStr.replace(/\s*/g, '')

  return newStr
}

// 计算一行能容纳几个容器
export const calculationWrapper = (options = {}) => {
  const { width, data, wrapperWidth } = options

  if (!width) {
    return []
  }

  const arr = []

  let count = parseInt(width / wrapperWidth)

  if (count < 1) {
    count = 1
  }

  for (let i = 1; i <= count; i++) {
    arr.push([])
  }

  data.map((item, index) => {
    const arrIndex = index % count

    arr[arrIndex].push(item)
  })

  return arr
}

// 导出excel
function getCellWidth (value) {
  // 判断是否为null或undefined
  if (value == null) {
    return 10
  } else if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
    // 中文的长度
    const chineseLength = value.match(/[\u4e00-\u9fa5]/g).length
    // 其他不是中文的长度
    const otherLength = value.length - chineseLength
    return chineseLength * 2.1 + otherLength * 1.1
  } else {
    return value.toString().length * 1.1
    /* 另一种方案
    value = value.toString()
    return value.replace(/[\u0391-\uFFE5]/g, 'aa').length
    */
  }
}

/**
 * 将table、json数据导出为excel
 * @param {object} options
 * @param {[]} options.data 数据源
 * @param {'table'|'json'|'aoe'} options.dataType 数据类型
 * @param {string} options.sheetName sheet名称
 * @param {boolean} options.saveFile 是否保存为文件，如果为false则返回workBook
 * @param {string} options.fileName 文件名称
 * @param {boolean} options.fitWidth是否自适应列宽(如果dataType='json',配置此属性将无效)
 * @param {[]} options.header xlsx内部参数
 */
export const exportExcel = (
  {
    data = [],
    merges = [],
    styles = {},
    dataType = 'json',
    sheetName = 'Sheet1',
    saveFile = true,
    fileName = new Date() + '.xlsx',
    fitWidth = true,
    header = [],
    skipHeader = false
  } = {}
) => {
  try {
    if (!XLSX) {
      console.log('exportTo: the plug-in XLSX is undefined.')
      return
    }
    if (!data || data.length === 0) {
      console.log('exportTo: data is null or undefined.')
      return
    }
    let sheet = {}
    switch (dataType) {
      case 'table':
        sheet = XLSX.utils.table_to_sheet(data, { raw: true })
        break
      case 'json':
        sheet = XLSX.utils.json_to_sheet(data, { raw: true, header, skipHeader })
        sheet['!merges'] = merges

        for (let key in styles) {
          if (sheet[key]) {
            sheet[key].s = styles[key]
          }
        }

        console.log(sheet)
        if (fitWidth) {
          let colWidths = []
          let colNames = Object.keys(data[0]) // 所有列的名称数组

          // 计算每一列的所有单元格宽度
          // 先遍历行
          data.forEach((row) => {
            // 列序号
            let index = 0
            // 遍历列
            for (const key in row) {
              if (colWidths[index] == null) colWidths[index] = []

              switch (typeof row[key]) {
                case 'string':
                case 'number':
                case 'boolean':
                  colWidths[index].push(getCellWidth(row[key]))
                  break
                case 'object':
                case 'function':
                  colWidths[index].push(0)
                  break
              }
              index++
            }
          })

          sheet['!cols'] = []
          // 每一列取最大值最为列宽
          colWidths.forEach((widths, index) => {
            // 计算列头的宽度
            widths.push(getCellWidth(colNames[index]))
            // 设置最大值为列宽
            sheet['!cols'].push({ wch: Math.max(...widths) })
          })
        }
        break
      case 'aoe':
        // 未实现
        sheet = []
        break
    }

    let workBook = {
      SheetNames: [sheetName],
      Sheets: {
        [sheetName]: sheet
      }
    }
    console.log(sheet)

    if (saveFile) {
      XLSX.writeFile(workBook, fileName)
      return true
    } else {
      return workBook
    }
  } catch (error) {
    console.error('exportTo: ', error)
    throw error
  }
}

// 增加合并单元格的变宽
export const xlsxAddRangeBorder = (range, ws) => {
  let arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

  range.forEach(item => {
    let startRowNumber = Number(item.s.c)
    let endRowNumber = Number(item.e.c)
    let startColNumber = Number(item.s.r)
    let endColNumber = Number(item.e.r)

    for (let i = startRowNumber + 1; i <= endRowNumber; i++) {
      ws[arr[i] + (Number(item.e.r) + 1)] = {t: 's', v: '', s: {border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}}}}
    }

    for (let i = startColNumber + 1; i <= endColNumber; i++) {
      ws[arr[startRowNumber] + (Number(i) + 1)] = {t: 's', v: '', s: {border: {top: {style: 'thin'}, left: {style: 'thin'}, bottom: {style: 'thin'}, right: {style: 'thin'}}}}
    }
  })

  return ws
}

export const exportExcel1 = (
  {
    data = [],
    merges = [],
    styles = {},
    cols = [],
    dataType = 'json',
    sheetName = 'Sheet1',
    saveFile = true,
    isAddRangeBorder = false,
    fileName = new Date() + '.xlsx',
    fitWidth = true,
    header = [],
    skipHeader = false
  } = {}
) => {
  try {
    if (!XLSX) {
      console.log('exportTo: the plug-in XLSX is undefined.')
      return
    }
    if (!data || data.length === 0) {
      console.log('exportTo: data is null or undefined.')
      return
    }

    const wb = XLSXS.utils.book_new()
    let sheet = {}

    switch (dataType) {
      case 'table':
        sheet = XLSX.utils.table_to_sheet(data, { raw: true })
        break
      case 'json':
        sheet = XLSX.utils.json_to_sheet(data, { raw: true, header, skipHeader })
        sheet['!merges'] = merges

        for (let key in styles) {
          if (sheet[key]) {
            sheet[key].s = styles[key]
          }
        }

        sheet['!cols'] = cols

        if (isAddRangeBorder) {
          sheet = xlsxAddRangeBorder(sheet['!merges'], sheet)
        }

        // sheet工作簿标题
        const sheetName = 'sheet1'

        XLSXS.utils.book_append_sheet(wb, sheet, sheetName)

        break
    }

    if (saveFile) {
      XLSXS.writeFile(wb, fileName)
    } else {
      return wb
    }
  } catch (error) {
    console.error('exportTo: ', error)
    throw error
  }
}

// 获取地址栏信息
export const getUrlParam = (name) => {
  var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
  var r = window.location.search.substr(1).match(reg)
  if (r != null) return unescape(r[2])
  return null
}

// 判断除0以外的空数据
export const hasValidData = (data) => {
  // 0是有效数据，null、undefined、空字符串、空数组、空对象是无效数据
  if (typeof data === 'number') return !isNaN(data);
  if (data === null || data === undefined) return false;
  return !isEmpty(data);
}
